﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;
using Microsoft.SharePoint.Administration.Health;

namespace SPHealth.SharePoint.HealthRules.SP.Rules.Configuration
{
    class ErrorVerifyRulesConfiguration : SPHealthAnalysisRule
    {
        #region Locals
        string results = "";
        #endregion

        #region Constructor
        /* This rules does not require a constructor */
        #endregion

        #region Fields

        // the category to display this rule under
        public override SPHealthCategory Category
        {
            get { return SPHealthCategory.Configuration; }
        }

        // the type or error to flag this rule as
        public override SPHealthCheckErrorLevel ErrorLevel
        {
            get { return SPHealthCheckErrorLevel.Error; }
        }

        // the Explanation for the rule and what is not working
        public override string Explanation
        {
            get { return string.Format("The settings for the following rules contain invalid XML:\r\n\r\n{0}", results); }
        }

        // how to fix the issue
        public override string Remedy
        {
            get { return "Please review the invalid settings listed above and ensure the settings are valid XML fragments. The XML should contain a single <Properties> node and a <Property> element for each setting. Each property element must contain a Key and a Value attribute."; }
        }

        // the Summary for the rule
        public override string Summary
        {
            get { return "One or more configuration settings for SPHealth.codeplex.com rules contain invalid XML."; }
        }

        public override SPHealthAnalysisRuleAutomaticExecutionParameters AutomaticExecutionParameters
        {
            get
            {
                SPHealthAnalysisRuleAutomaticExecutionParameters retval = new SPHealthAnalysisRuleAutomaticExecutionParameters();
                retval.Schedule = SPHealthCheckSchedule.Daily;
                retval.Scope = SPHealthCheckScope.Any;
                retval.ServiceType = typeof(SPTimerService);
                return retval;
            }
        }
        #endregion

        #region Methods

        // this method is called whenever the rule is executed
        public override SPHealthCheckStatus Check()
        {
            if (!SPFarm.Joined)
                throw new InvalidOperationException();

            // setup
            results = "";
            StringBuilder sb = new StringBuilder();

            // get each configuration rule setting and validate the XML
            using (SPWeb centralAdminWeb = common.GetCentralAdminWeb())
            {
                SPList configList = centralAdminWeb.Lists.TryGetList(common.LIST_RuleConfigurations);
                if (configList != null)
                {
                    foreach (SPListItem configItem in configList.Items)
                    {
                        string error = "";
                        try
                        {
                            // convert our settings to xml
                            XmlDocument doc = new XmlDocument();
                            doc.LoadXml(configItem["Settings"].ToString());

                            // test our settings structure
                            try
                            {
                                XmlNode properties = doc.SelectSingleNode("/Properties");
                                if (properties == null)
                                    throw new Exception();

                                foreach (XmlNode property in properties.SelectNodes("Property"))
                                {
                                    try
                                    {
                                        string key = property.Attributes["Key"].Value;
                                        if (string.IsNullOrEmpty(key))
                                            error = "key attribute empty";
                                    }
                                    catch
                                    {
                                        error = "key attribute missing";
                                    }
                                    try
                                    {
                                        string val = property.Attributes["Value"].Value;
                                        if (string.IsNullOrEmpty(val))
                                            error = "value attribute empty";
                                    }
                                    catch
                                    {
                                        error = "value attribute missing";
                                    }
                                }

                            }
                            catch
                            {
                                error = "properties node not found.";
                            }
                        }
                        catch
                        {
                            error = "invalid XML";
                        }
                        finally
                        {
                            //  log the error
                            if (!string.IsNullOrEmpty(error))
                                sb.AppendLine(string.Format("{0} - {1}", configItem.Title, error));
                        }
                    }
                }

            }

            // determine if the check has passed or failed.
            results = sb.ToString();
            if (!string.IsNullOrEmpty(results))
                return SPHealthCheckStatus.Failed;
            else
                return SPHealthCheckStatus.Passed;
        }

        #endregion

    }
}
